package com.ebook.server.service;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.ebook.core.domain.Note;
import com.ebook.core.util.NoteUtil;
import com.ebook.server.dao.NoteDao;
import com.ebook.util.DateUtil;
import com.ebook.util.ErrorCode;
import com.ebook.util.FileUtil;
import com.ebook.util.Status;
import com.ebook.util.ZipUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

@Service
@Transactional
public class NoteService {

	@Resource
	private JdbcTemplate jdbcTemplate;

	@Resource
	private UserService userService;
	
	@Resource
	private NoteDao noteDao;
	
	@Resource
	private ReturnNoteService returnNoteService;
	
	@Resource
	private DeviceBookService deviceBookService;

//	private static final String NOTE_FILE_PATH = "/opt/ebook/data/note/";

		private static final String NOTE_FILE_PATH = "c:/opt/ebook/data/note/";

	private static Log logger = LogFactory.getLog(NoteService.class);


	/**
	 * 根据笔记id删除一条笔记 和 服务器zip文件包
	 * @param noteIdsJson 笔记ids
	 * @param uid         用户id
	 * @param request
	 * @return            删除成功、失败信息
	 */
	public ModelAndView delNoteAndZip(String noteIdsJson, int uid, int bookid,String device_id,String verificationCode) {
		Map<String, Object> modelMap = new HashMap<String, Object>();
		String status = Status.FAIL;
		if (!userService.isCertified(uid, verificationCode)) {
			modelMap.put("status", Status.FAIL);
			return new ModelAndView().addAllObjects(modelMap);
		}
		List<Note> list = new Gson().fromJson(noteIdsJson, new TypeToken<List<Note>>() {
		}.getType());
		if (updateNotExistByNoteids(list,uid,bookid,device_id)) {
			status = Status.SUCCESS;
		} else {
			status = Status.REJECTED + ":" + ErrorCode.NOTE_DEL_FAIL;	
		}
		modelMap.put("status", status);
		return new ModelAndView().addAllObjects(modelMap);
	}
	
	@Transactional(rollbackFor = Exception.class)
	public  ModelAndView determineSync(int uid, int bookid,String device_id,String verificationCode) {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		String status = Status.FAIL;
		if (!userService.isCertified(uid, verificationCode)) {
			modelMap.put("status", Status.FAIL);
			return new ModelAndView().addAllObjects(modelMap);
		}
		deviceBookService.updateAfterSyncTime(DateUtil.dateToLong(new Date()), device_id, bookid);
		setNeedReturn(uid,bookid,device_id);
		status = Status.SUCCESS;
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}
	
	/**
	 * 同步整合之前的操作
	 * <p>
	 * 1、获取当前时间为本次同步完成时间</br>
	 * 2、设置需要返回笔记的标记</br>
	 * @param uid
	 * @param bookid
	 * @param device_id 
	*/
	@Transactional(rollbackFor = Exception.class)
	public  void determineSync(int uid, int bookid,String device_id) {
		deviceBookService.updateAfterSyncTime(DateUtil.dateToLong(new Date()), device_id, bookid);
		setNeedReturn(uid,bookid,device_id);
	}
	
	@Transactional(rollbackFor = Exception.class)
	private void setNeedReturn(int uid,int bookid,String device_id){
		long startTime = deviceBookService.findNoteSyncTime(device_id, bookid);
		if(startTime == -1){
			return ;
		}
		List<Note> noteList = queryByCnd(uid, bookid,startTime);
		if(noteList.isEmpty()){
			return ;
		}
		for(Note n : noteList){
			returnNoteService.insert(n.getNoteid(), device_id,bookid, 0);
		}		
	}
	
	@Transactional(rollbackFor = Exception.class)
	public  ModelAndView getLatestNote(int uid, int bookid,String device_id,String verificationCode) {
		Map<String, Object> modelMap = new HashMap<String, Object>();
		List<Note> list = null;
		String status = Status.FAIL;
		if (!userService.isCertified(uid, verificationCode)) {
			modelMap.put("status", Status.FAIL);
			return new ModelAndView().addAllObjects(modelMap);
		}
		long lastSyncTime = deviceBookService.findNoteSyncTime(device_id, bookid);
		list = queryToClient(uid,bookid,device_id,lastSyncTime);
		returnNoteService.delete(device_id, bookid);
		deviceBookService.updateNoteSyncTime(deviceBookService.findAfterSyncTime(device_id, bookid), device_id, bookid);
		delByUploadTimeLessThanLastSyncTime(uid,bookid);
		modelMap.put("notelist",list);
		status = Status.SUCCESS;
		modelMap.put("status", status);
		return new ModelAndView().addAllObjects(modelMap);
	}
	
	@Transactional(rollbackFor = Exception.class)
	public  List<Note> getLatestNote(int uid, int bookid,String device_id) {
		List<Note> list = null;
		long lastSyncTime = deviceBookService.findNoteSyncTime(device_id, bookid);
		list = queryToClient(uid,bookid,device_id,lastSyncTime);
		returnNoteService.delete(device_id, bookid);
		deviceBookService.updateNoteSyncTime(deviceBookService.findAfterSyncTime(device_id, bookid), device_id, bookid);
		delByUploadTimeLessThanLastSyncTime(uid,bookid);
		return list;
	}
	

	/**
	 * 删除笔记信息中upload_time < 同一用户不同设备同一本书最小的更新时间的笔记信息
	 * <p>
	 * 获取同一用户不同设备同一本书最小的更新时间</br>
	 * 删除比它小的isExist=0的笔记信息
	 * @param uid
	 * @param bookid 
	*/
	private void delByUploadTimeLessThanLastSyncTime(int uid, int bookid) {
		long lastSyncTime = deviceBookService.findNoteSyncTimeBySameUser(uid, bookid);
		noteDao.deleteByUploadTime(uid, bookid, lastSyncTime);
	}
	@Transactional(rollbackFor = Exception.class)
	public ModelAndView isReading(int uid, int bookid,String device_id,String verificationCode) {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		String status = "Reading";
		if (!userService.isCertified(uid, verificationCode)) {
			modelMap.put("status", status);
			return new ModelAndView().addAllObjects(modelMap);
		}
		long seconds = new Date().getTime()/1000;
		if(deviceBookService.countOnlineSameBookByCnd(uid, bookid, device_id, seconds-60) > 0){
			status = "Reading";
		}else{
			status = "NoReading";
			deviceBookService.updateReadingTime(bookid, device_id, seconds);
		}
		System.out.println(seconds + "\t" + status);
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}

	@Transactional(rollbackFor = Exception.class)
	public ModelAndView isNoteExists(int uid, int bookid,String verificationCode) {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		String status = Status.FAIL;
		if (!userService.isCertified(uid, verificationCode)) {
			modelMap.put("status", Status.FAIL);
			return new ModelAndView().addAllObjects(modelMap);
		}
		modelMap.put("flag",noteDao.countNoteByUidAndBookid(uid,bookid)>0 ? "Exist" : "None");
		status = Status.SUCCESS;
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}

	public List<Note> getNoteByUidAndBookid(int uid, int bookid) {
		List<Note> noteList = new ArrayList<Note>();
		String selectNoteidSql = "select * from note where uid=? and bookid=? ";
		logger.info(selectNoteidSql);
		List<Map<String, Object>> maps = jdbcTemplate.queryForList(selectNoteidSql, uid, bookid);
		if (maps.size() > 0) {
			for (Map<String, Object> map : maps) {
				Note note = NoteUtil.parseNote(map);
				if (note != null) {
					noteList.add(note);
				}
			}
		}
		return noteList;

	}

	/**
	 * 通过uid和noteid获取服务器相对应的zip文件包
	 * @param uid       用户id
	 * @param bookid    图书id
	 * @param noteid    笔记id
	 * @param request   
	 * @return 成功、失败信息
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class)
	public ModelAndView getNoteZipFromServer(int uid, int bookid, String noteid, String verificationCode,
			HttpServletRequest request,HttpServletResponse response) throws Exception {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		if (!userService.isCertified(uid, verificationCode)) {
			modelMap.put("status", Status.FAIL);
			return new ModelAndView().addAllObjects(modelMap);
		}
		String status = Status.SUCCESS;
		String filePath = getFilePath(uid, bookid, noteid);
		if (!FileUtil.downloadZip(filePath, request, response)) {
			status = Status.REJECTED + ":" + ErrorCode.NOTE_GETZIP_FAIL;
		} else {
			modelMap.put("noteid", noteid);
		}
		//		 }
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}

	/**
	 * 获取文件的地址
	 * 格式：/opt/ebook/data/note/uid/bookid/noteid.zip
	 * @param uid
	 * @param bookid
	 * @param noteid
	 * @return 文件地址
	*/
	private String getFilePath(int uid, int bookid, String noteid) {
		StringBuilder directory = new StringBuilder(NOTE_FILE_PATH);
		directory.append(uid).append("/").append(bookid);
		File f = new File(directory.toString());
		if (!f.exists()) {
			f.mkdirs();
		}
		return directory.append("/").append(noteid).append(".zip").toString();
	}

	/**
	 * 根据noteId 删除笔记()
	 * <p>
	 * 把笔记状态设置为不存在，删除zip文件
	 * @param noteIds 笔记ids
	 * @param uid
	 * @param bookid
	 * @param device_id
	 * @return boolean
	*/
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public boolean updateNotExistByNoteids(List<Note> noteIds,int uid,int bookid,String device_id) {
		for (int i = 0; i < noteIds.size(); i++) {
			if(noteDao.isNoteExist(noteIds.get(i))){
				if(noteDao.updateNotExists(noteIds.get(i).getNoteid(), getSyncTime(device_id, bookid))){
					deleteNoteZip(noteIds.get(i), uid, bookid);
				}else{
					return false;
				}
			}else{
				deleteNoteZip(noteIds.get(i), uid, bookid);
			}
		}
		return true;
	}
	
	


	/**
	 * 根据 笔记Id 删除服务器zip文件包
	 * @param noteIds 笔记Ids
	 * @param uid     用户id
	 */
	public void deleteNoteZip(Note note, int uid, int bookid) {
			String filePath = getFilePath(uid, bookid, note.getNoteid());
			logger.info("deleteFilePath: " + filePath);
			File fileZip = new File(filePath);
			if (fileZip.exists()) {
				fileZip.delete();
			}
	}


	private List<Note> queryByCnd(int uid, int bookid){
		return queryByCnd(uid, bookid, -1, -1, -1,null);
	}
	
	private List<Note> queryByCnd(int uid, int bookid,int isExist){
		return queryByCnd(uid, bookid, -1,isExist, -1,null);
	} 
	
	private List<Note> queryByCnd(int uid, int bookid,long startTime){
		return queryByCnd(uid, bookid, -1,-1,startTime,null);
	} 
	
	
	/**
	 * 根据查询条件获取笔记信息</br>
	 * 如果查询条件为-1，则没有此条件
	 * @param uid
	 * @param bookid
	 * @param curr_chapter 笔记所在章节
	 * @param isExist 笔记存在状态（1：存在，0：不存在）
	 * @param startTime 上次笔记同步时间
	 * @param endTime 本次笔记同步时间
	 * @param noteid
	 * @return 笔记列表
	*/
	private List<Note> queryByCnd(int uid, int bookid, int curr_chapter,int isExist,long startTime,String noteid) {
		List<Map<String, Object>> list = null;
		if(curr_chapter == -1 && isExist == -1 && startTime == -1  && noteid == null){
			String sql = "select * from note where uid=? and bookid=?";
			list = jdbcTemplate.queryForList(sql, uid, bookid);
			
		}
		if(curr_chapter == -1 && startTime == -1  && noteid == null){
			String sql = "select * from note where uid=? and bookid=? and isExist=?";
			list = jdbcTemplate.queryForList(sql, uid, bookid,isExist);
		}
		if(curr_chapter == -1 && isExist == -1 && noteid == null){
			String sql = "select * from note where uid=? and bookid=? and upload_time>?";
			list = jdbcTemplate.queryForList(sql, uid, bookid,startTime);
		}
		if(curr_chapter != -1 && noteid != null){
			String sql = "select * from note where (uid=? and bookid=? and isExist=?  and curr_chapter=? and upload_time>?) or noteid=?";
			if(startTime == 12345){
				sql = "select * from note where (uid=? and bookid=? and isExist=?  and curr_chapter=? and upload_time>=?) or noteid=?";
			}
			list = jdbcTemplate.queryForList(sql, uid, bookid,isExist,curr_chapter,startTime,noteid);
		}
		List<Note> noteList = new ArrayList<Note>();
		if (list.isEmpty()) {
			return new ArrayList<Note>();
		}
		for (Map<String, Object> map : list) {
			Note note = NoteUtil.parseNote(map);
			noteList.add(note);
		}
		return noteList;
	}
	
	
	/**
	 * 判断两个cfi的大小
	 * @param cfi1
	 * @param cfi2
	 * @return -1：＜    ；   1：＞     ；   0：== 
	*/
	private int compareCfi(String cfi1,String cfi2){
//		logger.info("cfi1:");
		int[] array1 = getStringData(cfi1);
//		logger.info("cfi2:");
		int[] array2 = getStringData(cfi2);
//		logger.info("\n");
		int count = (array1.length > array2.length)?array2.length:array1.length;
	    if (count > 0) {
	        for (int i = 1; i<count; i++) {
	            if (array1[i] != array2[i]) {
	                if (array1[i] > array2[i]) {
	                    return 1;
	                }else{
	                    return -1;
	                }
	            }else{
	                if (i == count - 1) {
	                    return 0;
	                }else{
	                    continue;
	                }
	            }
	        }
	        
	    }
	    return 3;
	}
	

	
	/**
	 * 根据高亮的内容整合的笔记列表,并返回serverList
	 * @param localList 本地笔记列表
	 * @param serverList 数据库笔记列表
	 * @param uid
	 * @param bookid
	 * @param noteFile
	 * @return 笔记列表
	*/
	@Transactional(rollbackFor = Exception.class)
	public List<Note> getMergerList(List<Note> localList, List<Note> serverList, int uid, int bookid,String device_id,
			MultipartFile noteFile) {
		for (Note localNote : localList) {
			List<Note> needMergerList = new ArrayList<Note>();
//			flag_merger标记笔记是否和其他笔记有交集，false：没有交集；true：有交集(包含、交集)
			boolean flag_merger = false;
			String startCFIStr = localNote.getStartCFI();
			String endCFIStr = localNote.getEndCFI();
			for(int i =0;i<serverList.size();i++){
				logger.info("startCFIStr:"+startCFIStr);
				logger.info("endCFIStr:"+endCFIStr);
				logger.info("startCFIServer:"+serverList.get(i).getStartCFI());
				logger.info("endCFIServer:"+serverList.get(i).getEndCFI());
				if(compareCfi(startCFIStr,serverList.get(i).getStartCFI())==0 && compareCfi(endCFIStr,serverList.get(i).getEndCFI())==0){
//					a1==b1 && a2==b2 a==b 对比更新时间
					System.out.println("-----a == b ---------");
					flag_merger = true;
					localNote.setStartCFI(startCFIStr);
					localNote.setEndCFI(endCFIStr);
					updateByUpdateTime(localNote, serverList.get(i), uid, bookid,device_id, noteFile);
				}
				else if ((compareCfi(startCFIStr,serverList.get(i).getStartCFI())==-1 ||compareCfi(startCFIStr,serverList.get(i).getStartCFI())==0)
						 && (compareCfi( serverList.get(i).getEndCFI(),endCFIStr)==-1||compareCfi(serverList.get(i).getEndCFI(),endCFIStr)==0)){
//					 a1<=b1 && b2<=a2 a包含b
					System.out.println("-----a 包含   b ---------");
					 flag_merger = true;
					 needMergerList.add(serverList.get(i));
			    }else if ((compareCfi(serverList.get(i).getStartCFI(), startCFIStr)==-1||compareCfi(serverList.get(i).getStartCFI(), startCFIStr)==0)
			        		&& (compareCfi(serverList.get(i).getEndCFI(), endCFIStr)==-1||compareCfi(serverList.get(i).getEndCFI(), endCFIStr)==0)
			        		&&(compareCfi(startCFIStr, serverList.get(i).getEndCFI())==-1||compareCfi(startCFIStr, serverList.get(i).getEndCFI())==0)) {
//			         b1<=a1 && b2<=a2 && a1<=b2 a与b有交集，a>b
			    	System.out.println("-----a与b有交集，a>b ---------");
			        	startCFIStr = serverList.get(i).getStartCFI();
			        	flag_merger = true;
			        	needMergerList.add(serverList.get(i));
			    }else if((compareCfi(serverList.get(i).getStartCFI(), startCFIStr)==-1||compareCfi(serverList.get(i).getStartCFI(), startCFIStr)==0) 
			        		&& (compareCfi(endCFIStr, serverList.get(i).getEndCFI())==-1||compareCfi(endCFIStr, serverList.get(i).getEndCFI())==0)){
//			   b1<=a1 && a2<=b2 b包含a
			    	System.out.println("-----b 包含  a ---------");
			    	startCFIStr = serverList.get(i).getStartCFI();
			    	endCFIStr = serverList.get(i).getEndCFI();
			    	needMergerList.add(serverList.get(i));
			    	flag_merger = true;
			    }else if((compareCfi(startCFIStr,serverList.get(i).getStartCFI())==-1||compareCfi(startCFIStr,serverList.get(i).getStartCFI())==0) 
			        		&& (compareCfi(endCFIStr, serverList.get(i).getEndCFI())==-1||compareCfi(endCFIStr, serverList.get(i).getEndCFI())==0)
			        		&&(compareCfi(serverList.get(i).getStartCFI(), endCFIStr)==-1||compareCfi(serverList.get(i).getStartCFI(), endCFIStr)==0)){
			    	needMergerList.add(serverList.get(i));
//			        a1<=b1 && a2<=b2 && b1<=a2 a与b有交集，a<b
			    	System.out.println("-----a与b有交集，a<b ---------");
			        	endCFIStr = serverList.get(i).getEndCFI();
			        	flag_merger = true;
			        	needMergerList.add(serverList.get(i));	
			        }	
			}

			if (!flag_merger && !noteDao.isNoteExist(localNote)) {
				System.out.println("-----当前cfi与其他cfi无交集 ---------");
				if (localNote.getContain_file() == 1) {
					addZip(localNote, uid, bookid, noteFile);
				}
//				插入笔记到服务器，设置update_time为笔记更新时间，sync_time为同步时间点，并设置不返回标记。
				noteDao.insertExists(localNote, uid, false, getSyncTime(device_id, bookid));
				returnNoteService.updateNoReturnData(localNote.getNoteid(), device_id,bookid);
			}
			if (flag_merger) {
				//				如果有需要整合的数据，进行整合
				if (needMergerList.size() > 0) {
					serverList.removeAll(needMergerList);
					serverList.add(updateLocalNote(localNote, needMergerList, startCFIStr, endCFIStr));
				}

			}
//			logger.info("-------needMergerList----------");
//			for (Note note : needMergerList) {
//				logger.info(note.toString());
//			}
//			logger.info("-------分步整合的list----------");
//			for (Note note : serverList) {
//				logger.info(note.toString());
//			}

		}
//		logger.info("--------最终整合的list---------");
//		for (Note note : serverList) {
//			logger.info(note.toString());
//		}
//		logger.info("--------end---------");
		return serverList;

	}

	
	/**
	 * 修改本地笔记高亮内容，如果高亮内容与数据库的笔记有交集，则记录数据库笔记id和flag标志位
	 * 如：noteIdsAndFlag=20130609155639398000,needAdd;20130609155639398111,needAdd;
	 * @param localMap 本地某条笔记
	 * @param listCFI 笔记高亮位置信息数组列表
	 * @param needMergerList 需要整合的笔记列表
	 * @return 修改后的笔记内容
	*/
	private Note updateLocalNote(Note localNote, List<Note> needMergerList, String startCFIStr, String endCFIStr) {
		StringBuilder sb = new StringBuilder();
		for (Note note : needMergerList) {
			if (!"".equals(note.getFlag())) {
				if (!"".equals(note.getNoteIdsAndFlag())) {
					sb.append(note.getNoteid()).append(",").append(note.getFlag()).append(";")
							.append(note.getNoteIdsAndFlag());
				} else {
					sb.append(note.getNoteid()).append(",").append(note.getFlag()).append(";");
				}
			} else {
				if (!"".equals(note.getNoteIdsAndFlag())) {
					sb.append(note.getNoteid()).append(",").append("").append(";").append(note.getNoteIdsAndFlag());
				} else {
					sb.append(note.getNoteid()).append(",").append("").append(";");
				}
			}
		}
		if (sb.length() > 0) {
			localNote.setNoteIdsAndFlag(sb.toString());
		}
		logger.info("startCFIStr:" + startCFIStr + "\tendCFIStr:" + endCFIStr);
		localNote.setStartCFI(startCFIStr);
		localNote.setEndCFI(endCFIStr);
		localNote.setFlag("needAdd");
		return localNote;
	}

	private void updateByUpdateTime(Note localNote, Note serverNote, int uid, int bookid,String device_id, MultipartFile noteFile) {
		if (localNote.getUpdate_time() > serverNote.getUpdate_time()) {
			if (serverNote.getContain_file() == 1) {
				deleteZip(serverNote, uid, bookid);
			}
			if (localNote.getContain_file() == 1) {
				addZip(localNote, uid, bookid, noteFile);
			}	
//			更新本地笔记到服务器并设置upload时间为同步时间点；如果是同步操作，则设置不返回标记
			noteDao.updateExists(localNote, uid, getSyncTime(device_id, bookid));
				returnNoteService.updateNoReturnData(localNote.getNoteid(), device_id,bookid);
				returnNoteService.updateNoReturnData(serverNote.getNoteid(), device_id,bookid);	
		}else{
//			更新服务器笔记并设置upload时间为当前时间；如果是同步操作，则设置要返回标记
			noteDao.updateExists(serverNote, uid, getSyncTime(device_id, bookid));
			returnNoteService.updateReturnData(serverNote.getNoteid(), device_id, bookid);
		}
	}

	/**
	 * 将高亮位置信息字符串解析成数组来比对每位的数据
	 * @param startCFI
	 * @param endCFI
	 * @return 带有高亮位置信息的数组列表
	*/
	public static List<int[]> getCFIData(String startCFI, String endCFI) {
		List<int[]> list = new ArrayList<int[]>();
		System.out.print("\nstartdata:");
		list.add(getStringData(startCFI));
		System.out.print("\nendfdata: ");
		list.add(getStringData(endCFI));
		System.out.print("\n");
		return list;
	}

	/**
	 * 把字符串解析成7位的数组
	 * @param str 要解析的字符串
	 * @return 数组
	*/
	private static int[] getStringData(String str) {
		String[] s = str.substring(str.indexOf("(") + 1, str.indexOf(")")).split("!");
		int length = str.split("/").length;
		int[] data = new int[length];
		int i = 0;
		for (String s1 : s) {
			String[] s2 = s1.split("/");
			for (String ss2 : s2) {
				if (!"".equals(ss2)) {
					if (ss2.indexOf("[") != -1) {
						data[i++] = Integer.valueOf(ss2.substring(0, ss2.indexOf("[")));
					} else if (ss2.contains(":")) {
						data[length - 2] = Integer.valueOf(ss2.substring(0, ss2.indexOf(":")));
						data[length - 1] = Integer.valueOf(ss2.substring(ss2.indexOf(":") + 1));
					} else {
						data[i++] = Integer.valueOf(ss2);
					}
				}
			}
		}
		/*for (int k : data) {
			System.out.print("\t" + k);
		}*/
		return data;
	}

	/**
	 * 笔记同步
	*/
	@Transactional(rollbackFor = Exception.class)
	public ModelAndView syncNote(MultipartFile noteFile, int uid, int bookid,String device_id,String isSync, String noteJson,String verificationCode) {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		String status = Status.FAIL;
		String single = "false";
		if (!userService.isCertified(uid, verificationCode)) {
			modelMap.put("status", Status.FAIL);
			return new ModelAndView().addAllObjects(modelMap);
		}
		List<Note> localList = null;
		Gson gson = new Gson();
		try {
			localList = gson.fromJson(noteJson,new TypeToken<List<Note>>() {}.getType());
		} catch (Exception e) {
			logger.error("Json串解析成Note对象失败！" + e);
			throw new RuntimeException(e);
		}
		if(isSync == null){
			determineSync(uid, bookid, device_id);
		}
		mergerNote(noteFile, uid, bookid, device_id, localList);
		if(isSync == null){
			List<Note> list = getLatestNote(uid, bookid, device_id);
			modelMap.put("notelist", list);
			single = "true";
		}
		status = Status.SUCCESS;
		modelMap.put("single", single);
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}


	
	/**
	 * 根据本地已有的笔记整合笔记信息
	 * <p>
	 * 1、获取数据库笔记信息serverList(>startTime or ==noteId)</br>
	 * 2、如果serverList == null ，直接插入；否则，需要整合
	 * @param noteFile
	 * @param uid
	 * @param bookid
	 * @param device_id
	 * @param localList  本地已有的笔记
	*/
	private synchronized void mergerNote(MultipartFile noteFile, int uid, int bookid,String device_id, List<Note> localList) {
		long startTime = deviceBookService.findNoteSyncTime(device_id, bookid);
		List<Note> serverList = queryByCnd(uid, bookid,localList.get(0).getCurr_chapter(), 1, startTime,localList.get(0).getNoteid());
		System.out.println("serverList长度"+serverList.size());
		if (!"[{}]".equals(localList.toString())) {
			if (serverList.size()== 0) {
				for (Note note : localList) {
					if (noteFile != null) {
						String toFilePath = getFilePath(uid, bookid, note.getNoteid());
						FileUtil.writeTo(noteFile, toFilePath);
					}
//					插入设置update_time为笔记更新时间，upload_tiem为此次同步时间，并设置不返回标记
					noteDao.insertExists(note, uid,false,getSyncTime(device_id, bookid));
					returnNoteService.updateNoReturnData(note.getNoteid(), device_id,bookid);
					
				}
			} else {
				mergerData(localList, getMergerList(localList, serverList, uid, bookid,device_id, noteFile), uid,device_id, noteFile);
			}
		}

	}

	/**
	 * 整合重复高亮的内容
	 * <p>
	 * 思路：判断list中，某条笔记是否有"noteIdsAndFlag"字段，如果有责这个记录就是要整合的。
	 * @param localList 地笔记列表
	 * @param serverList 要整合的笔记列表
	 * @param uid
	 * @param device_id
	 * @param noteFile 
	*/
	private void mergerData(List<Note> localList, List<Note> serverList, int uid,String device_id, MultipartFile noteFile) {
		if (serverList.isEmpty()) {
			return;
		}
		for (Note note : serverList) {
			if (!"".equals(note.getNoteIdsAndFlag())) {
//				把该笔记更新为不存在，并且设置upload_time为after_sync_time,设置该笔记需要返回的标记
				updateDataNotExist(note, uid, device_id);
				returnNoteService.updateReturnData(note.getNoteid(), device_id, note.getBookid());
				note.setNoteid(getNewNoteId());
				String noteIdsAndFlag = note.getNoteIdsAndFlag().substring(0, note.getNoteIdsAndFlag().length() - 1);
				String[] noteIdsAndFlags = noteIdsAndFlag.split(";");
				for (String noteIds : noteIdsAndFlags) {
					String noteId = noteIds.substring(0, noteIds.indexOf(","));
					String flag = noteIds.substring(noteIds.indexOf(",") + 1);
					logger.info("----------要整合的noteid和flag(flag=空字符时代表这个noteid是数据库的)------------");
					logger.info("noteId:" + noteId);
					logger.info("flag:" + flag);
					if (flag.equals("needAdd")) {
						//					去localList中去找相应的数据信息，再整合
						for (Note localNote : localList) {
							if (localNote.getNoteid().equals(noteId)) {
								mergerLocalData(localNote, note);
							}
						}
					} else {
//						直接整合数据库信息	
						mergerServerData(noteId, note,device_id);
					}
				}
				if (noteFile != null) {
					addZip(note, uid, note.getBookid(), noteFile);
					mergerZip(note.getNoteid(), note);
					deleteZip(note, uid, note.getBookid());
				}
				if (note.getContain_file() == 1) {
//					将整合的文件压缩成zip格式
					String srcPath = getUnZipDirectory(note);
					String destPath = getFilePath(note.getUid(), note.getBookid(), note.getNoteid());
					try {
						ZipUtils.compress(srcPath, destPath);
					} catch (Exception e) {
						logger.error("压缩zip文件失败！" + e);
					}
					try {
						FileUtils.deleteDirectory(new File(getUnZipDirectory(note)));
					} catch (IOException e) {
						logger.error("循环删除文件失败！" + e);

					}
				}
				note.setNote_index(Integer.valueOf(note.getNoteid().substring(note.getNoteid().length()-5)));
//				插入笔记到服务器，并且设置update_time为当前时间，sync_time为after_sync_time，并设置返回标记
				noteDao.insertExists(note, uid, true, getSyncTime(device_id, note.getBookid()));
				returnNoteService.updateReturnData(note.getNoteid(), device_id, note.getBookid());
				logger.info("---------select_content-----------");
				logger.info(note.getSelect_content());

			}
		}

	}

	private String getNewNoteId() {
		SimpleDateFormat SDF4 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		return SDF4.format(new Date());

	}

	/**
	 * 整合数据库的笔记内容，整合后删除数据库存在的该条笔记
	 * @param noteId 笔记id
	 * @param localMap 本地笔记
	 * @param device_id
	*/
	private void mergerServerData(String noteId, Note localNote,String device_id) {
		Map<String, Object> serverMap = noteDao.queryByNoteid(noteId);
		if (serverMap != null) {
			Note serverNote = NoteUtil.parseNote(serverMap);
			StringBuilder select_content = new StringBuilder(localNote.getSelect_content());
			select_content.append("\n").append(serverNote.getSelect_content()).append("\n");
			localNote.setSelect_content(select_content.toString());
			if(localNote.getIsNote() == 0){
				localNote.setIsNote(serverNote.getIsNote());
			}
			//			整合zip包到新的noteid下
			if (serverNote.getContain_file() == 1) {
				mergerZip(noteId, localNote);
				localNote.setContain_file(1);
			}
//			把该笔记更新为不存在，并且设置sync_time为同步时间,并设置该笔记需要返回的标记
			noteDao.updateNotExists(noteId, getSyncTime(device_id, serverNote.getBookid()));
			returnNoteService.updateReturnData(noteId, device_id, serverNote.getBookid());
			deleteZip(serverNote, serverNote.getUid(), serverNote.getBookid());
		}

	}

	/**
	 * 合并笔记的zip包
	 * @param fromNoteId 
	 * @param toNote 
	*/
	private void mergerZip(String fromNoteId, Note toNote) {
		String fromPath = getFilePath(toNote.getUid(), toNote.getBookid(), fromNoteId);
		String toPath = getUnZipDirectory(toNote);
		try {
			ZipUtils.deCompressZip1(fromPath, toPath);
		} catch (IOException e) {
			e.printStackTrace();

		} catch (ArchiveException e) {
			e.printStackTrace();
		}
	}

	private String getUnZipDirectory(Note note) {
		StringBuilder unZipDirectory = new StringBuilder(NOTE_FILE_PATH);
		unZipDirectory.append(note.getUid()).append("/").append(note.getBookid()).append("/unzip/")
				.append(note.getNoteid());
		File f = new File(unZipDirectory.toString());
		if (!f.exists()) {
			f.mkdirs();
		}
		return unZipDirectory.toString();
	}

	/**
	 * 把本地的重复信息
	 * @param localMap 
	 * @param map 
	*/
	private void mergerLocalData(Note localNote, Note note) {
		StringBuilder select_content = new StringBuilder(note.getSelect_content());
		select_content.append("\n").append(localNote.getSelect_content()).append("\n");
		note.setSelect_content(select_content.toString());
		if(note.getIsNote() == 1){
			note.setIsNote(localNote.getIsNote());
		}
		if (localNote.getContain_file() == 1) {
			mergerZip(note.getNoteid(), localNote);
			deleteZip(localNote, localNote.getUid(), localNote.getBookid());
			note.setContain_file(1);
		}
	}

	private List<Note> queryToClient(int uid, int bookid, String device_id,long lastSyncTime) {
		List<Note> noteList = new ArrayList<Note>();
		List<Note> tempList = new ArrayList<Note>();
		List<Map<String,Object>> list = null;
//		如果同步时间为初始时间，则查询全部；否则按大于同步时间的查询
		if(lastSyncTime == 12345){
			tempList = queryByCnd(uid, bookid);
			return tempList;
		}else{
			list = returnNoteService.queryByCnd(device_id, bookid);
			if(list == null){
				return new ArrayList<Note>();
			}
			tempList = queryByCnd(uid, bookid, lastSyncTime);
			for(int i=0;i<tempList.size();i++){
				for(Map<String,Object> m : list){
					if(((String)m.get("noteid")).equals(tempList.get(i).getNoteid())){
						noteList.add(tempList.get(i));
					}
				}
			}
			return noteList;
		}	
	}

	
	private void updateDataNotExist(Note note,int uid,String device_id){
		if(noteDao.isNoteExist(note)){
			noteDao.updateNotExists(note.getNoteid(),getSyncTime(device_id, note.getBookid()));
		}else{
			noteDao.insertNotExists(note, uid,getSyncTime(device_id, note.getBookid()));
		}
	}
	

	public void deleteZip(Note note, int uid, int bookid) {
		String filePath = getFilePath(uid, bookid, note.getNoteid());
		logger.info("deleteFilePath: " + filePath);
		File fileZip = new File(filePath);
		if (fileZip.exists()) {
			fileZip.delete();
		}
	}

	public void addZip(Note note, int uid, int bookid, MultipartFile noteFile) {
		String toFilePath = getFilePath(uid, bookid, note.getNoteid());
		if (!new File(toFilePath).exists()) {
			FileUtil.writeTo(noteFile, toFilePath);
		}
	}
	

	/**
	 * 获取同步时间
	 * @param device_id
	 * @param bookid
	 * @return 同步时间
	*/
	private long getSyncTime(String device_id, int bookid) {
		return deviceBookService.findAfterSyncTime(device_id, bookid);
	}
}
